/**
 * @file face_detect.cc
 * @author your name (you@domain.com)
 * @brief 2号线程，调用人脸检测模型，用于低功耗启动判断
 * @version 0.1
 * @date 2023-2-02
 * 
 * @copyright Copyright (c) 2022
 * 
 */
#include "face_detect.h"      
#include <unistd.h>
#include <iostream>
#include <string>
#include <pthread.h>


#include "object_detect.h" 
#include "yolov5s_detect.h"

extern "C"{
    #include <signal.h>
    #include "rkmedia_api.h"
    #include "rk_nv12_to_rgb.h"
}

static void sig_proc(int signo) {
  printf("signal %d\n", signo);
}
extern int g_flag_run;
struct FaceDetectBuffer face_detect_buffer = {0,0,0,{0}};
extern uint8_t person_id;

//人脸检测，返回值是true or false；
static bool detect(cv::Mat img, cv::CascadeClassifier cascade)
{
    std::vector<cv::Rect> faces;
    cascade.detectMultiScale(img, faces, 1.2, 2);
    //Todo:人脸的位置不在主驾驶位，也认为是无人    
    if(faces.size() == 0)      
    {
        return false;
    }
    else 
    {
        return true;
    }
}

//统计buffer中各类别占据的比例，50和0为敏感值 
static int cnt_buffer(char *buffer){
    int cnt_face = 0;
    enum FaceExistFlag ret;
    for(int i = 0; i < 10; i++)   
    {
        if(buffer[i] == 1)
            cnt_face += 1;
        
        else;

        if(cnt_face >= 5){
            ret = FIFTY_PERCENT_FLAG;
            return ret;
        }; 
    }
    if(cnt_face == 0){
        ret = ZERO_FLAG;
        return ret;
    } 
    return 0;
}

void *face_detector(void *arg)
{
    uint8_t cpu_id = 2;
    //线程对cpu亲和性设定   
    cpu_set_t mask;
    CPU_ZERO(&mask);
    CPU_SET(cpu_id, &mask);
    pthread_t pthread_no_3;     //3号线程
    
    printf("Bind face_detector thread to CPU %d\n", cpu_id);

    //定义并使用人脸检测
    cv::CascadeClassifier cascade;
    std::string cascadeName = "model/haarcascade_frontalface_default.xml";
    if( !cascade.load( cascadeName ))
    {
        std::cerr << "ERROR: Could not load classifier cascade" << std::endl;
    }  

    MEDIA_BUFFER buffer = NULL;
    cv::Mat img = cv::Mat(1080, 1920, CV_8UC3);

    uint8_t status = LOW_ENERGY_WORKING;


    signal(SIGSEGV, sig_proc);
    while (g_flag_run) 
    {
        int ret;
        buffer = RK_MPI_SYS_GetMediaBuffer(RK_ID_VI, 1, -1);            //从1通道取数据
        if (!buffer)  continue;
        int rga_buffer_size = 1920 * 1080 * 3; // nv12 3/2, rgb 3
        unsigned char *rga_buffer = (unsigned char *)malloc(rga_buffer_size);
        
        nv12_to_rgb24((unsigned char *)RK_MPI_MB_GetPtr(buffer), rga_buffer,1920,1080);
        img.data = rga_buffer;

        // /*这一部分是保存1080P图像的功能代码*/
        // char str[20];
        // static int tmp_int = 0;
        // sprintf(str, "00%d_%d.jpg", person_id, tmp_int);
        // tmp_int += 1;
        // cv::imwrite(str, img);
        // printf("%d张img保存完毕\n", tmp_int);       

        cv::Mat img_resize = letterBox(img, 368, 368);
        ret = detect(img_resize, cascade);

        //检测结果入RingBuffer
        if(ret){
            face_detect_buffer.buffer[face_detect_buffer.id++] = 1;
            // printf("face_detect模块检测到驾驶位有人\n");
        }
        else face_detect_buffer.buffer[face_detect_buffer.id++] = 0; 

        if(face_detect_buffer.id == 10)  face_detect_buffer.id = 0;
        
        //判断驾驶员出现帧占RingBuffer的比例
        char *ringbuffer_buffer = face_detect_buffer.buffer;
        ret = cnt_buffer(ringbuffer_buffer);

        //进入状态机，判断
        switch(status){
            case LOW_ENERGY_WORKING:
            {
                if(ret == FIFTY_PERCENT_FLAG)
                {
                    status = NORMAL_WORKING;
                    pthread_create(&pthread_no_3, NULL, object_detect, NULL);
                }
                else    printf("目前处于低功耗工作模式\n");
                break;
                
            }
            case NORMAL_WORKING:
            {
                if(ret == ZERO_FLAG){
                    status = LOW_ENERGY_WORKING;
                    pthread_cancel(pthread_no_3);
                    //向3号线程发送Cancel信号后，如果不进行阻塞等待就会出现段错误
                    pthread_join(pthread_no_3, NULL);
                }
                else;
                break;
            }
            default:
            ;
        }       
        RK_MPI_MB_ReleaseBuffer(buffer);
        if (rga_buffer)
            free(rga_buffer);
        //延时700ms
        usleep(700000);
    }
}